home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / vtkerma1.arc / MSHELPER.ASM < prev    next >
Assembly Source File  |  1986-02-13  |  19KB  |  772 lines

  1.     PAGE 59, 132
  2.  
  3.     TITLE MsHelper -- Windowing help module for VT100 emulation on IBM PC
  4.  
  5. ; Update 6 Jan 86
  6.  
  7. IF1
  8.  %OUT >> Starting pass 1
  9. ELSE
  10.  %OUT >> Starting pass 2
  11. ENDIF
  12.  
  13.     PUBLIC Helper
  14.     .SALL
  15.  
  16. ;***************************************************************************
  17. ; *Definitions* ...
  18.  
  19. ; Global defs
  20.  
  21.     INCLUDE MsDefs.H
  22.  
  23. DataS    SEGMENT PUBLIC 'DataS'
  24.  
  25.     EXTRN Which_page:BYTE, Screen_flags:BYTE
  26.     EXTRN Video_page_addresses:WORD, m7171:BYTE
  27.     EXTRN Force_mono:BYTE, m7171:BYTE
  28.  
  29. Screen    EQU 10h            ; BIOS screen call
  30. Kb    EQU 16h            ; BIOS keyboard call
  31.  
  32. Old_7171_mode DB ?        ; If we were here before, which mode was it?
  33.  
  34. ; Screen stuff
  35.  
  36. Number_of_columns EQU 80    ; Width in characters
  37. Number_of_rows_PC EQU 25    ; Length in rows including mode line
  38. Number_of_chars_on_PC_screen EQU Number_of_columns*Number_of_rows_PC
  39.                 ; Number of chars in IBM screen
  40.  
  41. ; Flag set in Screen_flags
  42.  
  43. Screen_changed EQU 8        ; Data on more than one line changed
  44.  
  45. Saved_mode_line DW Number_of_columns DUP (?) ; Saved image of Mode line
  46.  
  47. ; Scan codes for keys we have predefined ...
  48.  
  49. Escape_key EQU 1
  50. Space_key EQU 57
  51. F6_key    EQU 64
  52. ALT_F6_key EQU 109
  53. End_key    EQU 79
  54. Down_key EQU 80
  55. PgDn_key EQU 81
  56. Left_key EQU 75
  57. Right_key EQU 77
  58. Home_key EQU 71
  59. Up_key EQU 72
  60. PgUp_key EQU 73
  61.  
  62. Characters LABEL BYTE
  63.     DB     Space_key,    Escape_key,    F6_key
  64.     DB    Home_key,    End_key,    PgUp_key
  65.     DB    PgDn_key,    Up_key,        Down_key
  66.     DB    Left_key,    Right_key,    ALT_F6_key
  67. N_Characters EQU $-Characters
  68. Actions    LABEL WORD
  69.     DW     CHK_bye,    CHK_bye,    CHK_bye
  70.     DW     Do_Home,    Do_End,        Do_PgUp
  71.     DW    Do_PgDn,    Do_Up,        Do_Down
  72.     DW    Do_Up,        Do_Down,    CHK_bye
  73.     DW    Do_boop
  74.  
  75.     PUBLIC Help_file_name, Characters, Actions
  76.  
  77. Help_file_name LABEL BYTE
  78.     Program_name
  79.     DB '.HLP',0        ; Name of our help file
  80.  
  81. Help_file_7171 LABEL BYTE
  82.     Program_name
  83.     DB '.H71',0        ; Name of our help file on IBM 7171
  84.  
  85. No_memory DB '      ***  Not enough memory for HELP  --  Press any key to continue ***$'
  86.  
  87. Cant_find_file DB '        *****   Missing '
  88.     Program_name
  89.     DB '.HLP  --  Press any key to continue  *****$'
  90.  
  91. Cant_find_7171 DB '        *****   Missing '
  92.     Program_name
  93.     DB '.H71  --  Press any key to continue  *****$'
  94.  
  95. DataS    ENDS
  96.  
  97.  
  98. ; Dummy segment for allocated memory
  99.  
  100. HAlloc    SEGMENT AT 0
  101.  
  102. First_line DW ?            ; Ptr to first line in database
  103. Last_line DW ?            ; Ptr to last line in database
  104. Last_top_line DW ?        ; Ptr to line on top of last frame
  105. Current_line DW ?        ; Ptr to line currently at top of window
  106.  
  107. Which_row DW ?            ; Which row are we writing in?
  108.  
  109.     PUBLIC Our_Image, Our_cursor, Which_row, Current_line, First_line
  110.  
  111. Our_cursor DW ?            ; Our position
  112. Our_Image DW Number_of_chars_on_PC_screen DUP (?) ; Our buffer
  113.  
  114.     PUBLIC Help_database, Help_file_buffer,End_HAlloc
  115.  
  116. Zero    DB ?            ; Make backward searches stop here ...
  117. Help_database DB 300*74 DUP (?)    ; Where we store the help text
  118.  
  119. Help_file_buffer DB 2048 DUP (?) ; Buffer for reading Help file from disk
  120.  
  121. End_HAlloc LABEL BYTE        ; Ptr to end of what we need
  122.  
  123. HAlloc    ENDS
  124.  
  125.  
  126. Code    SEGMENT PUBLIC
  127.  
  128.     EXTRN Put_Screen:NEAR, Get_Screen_Segment:NEAR, Boop:NEAR
  129.     EXTRN SPath:NEAR, Check_table:NEAR, Do_mode_line:NEAR
  130.     EXTRN Get_memory_block:NEAR, PutErr_PC:NEAR, Screen_Image_ptr:DWORD
  131.     EXTRN Which_card:BYTE, Mode_line_ptr:DWORD
  132.  
  133.     ASSUME CS:Code, DS:DataS, ES:DataS
  134.  
  135. Normal_ds DW ?            ; Ptr back to ds on entry
  136. HAlloc_ptr DW ?            ; Address of HAlloc segment
  137.  
  138.     PUBLIC HFlags
  139.  
  140. HFlags    DB 0            ; Internal flags, kept in code segment
  141.                 ;  for easy access
  142.  
  143. Bye_bye EQU 1            ; Flag to leave
  144. Been_here EQU 2            ; Already did once-only initialization
  145.  
  146. Helper    PROC
  147.  
  148.     and HFlags, NOT Bye_bye    ; Flag that we aren't leaving yet
  149.  
  150.     test HFlags, Been_here    ; Been here before?
  151.      jz HLP_go        ;  No ...
  152.  
  153. ; We have been here before, but maybe with the wrong help file ...
  154.  
  155.     mov al, m7171        ; Pick up current 7171 mode
  156.     cmp al, Old_7171_mode    ; Same as last time?
  157.      je HLP_1        ;  Same, just display our buffer
  158.  
  159. ; We have been here before, so we already have memory allocated ...
  160. ;  We just need to reload the database
  161.  
  162.     mov ax, HAlloc_ptr    ; Reuse old memory
  163.     jmp SHORT H_ok        ; Join common code
  164.  
  165. HLP_go:
  166.  
  167. ; First, get some memory to work in
  168.  
  169. ; *** The silly assembler won't let me do this, saying
  170. ;        Constant was expected
  171. ;    or something like that ...
  172.  
  173. ;    mov bx, (OFFSET End_HAlloc+15) SHR 4 ; Lowest location we don't use,
  174.                 ;  round up to next higher paragraph,
  175.                 ;  then convert to number of paragraphs
  176.  
  177.     mov bx, OFFSET End_HAlloc+15 ; Round up to next paragraph
  178.     mov cl, 4        ; Shift count
  179.     shr bx, cl        ; Shift to get number of paras we need
  180.  
  181.     call Get_memory_block    ; Get a memory block of the right size
  182.      jnc H_OK        ;  Ok so far ...
  183.  
  184.     mov dx, OFFSET No_memory ; Complain
  185.     jmp Do_mode_line_error    ; Display noisy error message, wait for
  186.                 ;  keystroke, then exit, restoring
  187.                 ;  clobbered mode line
  188.  
  189. H_OK:    mov HAlloc_ptr, ax    ; Save the address of our block
  190.  
  191.     mov bx, ds        ; Set up ptr back to ds
  192.     mov Normal_ds, bx    ; Save ptr back to old one
  193.  
  194. ; Switch to HAlloc segment ...
  195.  
  196.     mov ds, ax        ; Point ds to HAlloc
  197.     mov es, ax        ;  es also ...
  198.  
  199.     ASSUME ds:HAlloc, es:HAlloc    ; Tell assembler we have a new ds and es
  200.  
  201.     mov Zero, 0        ; Store a zero
  202.  
  203.     call Build_Help_database ; Build the database
  204.     test HFlags, Bye_bye    ; Time to leave?
  205.      jz HLP_0        ;  Not yet
  206.  
  207. ; *** Properly speaking, we really ought to release the memory we
  208. ;    were just allocated, since we can't use it ... maybe later ***
  209.  
  210.     jmp Back_to_normal_ds    ; Oh well ...
  211.  
  212. HLP_0:    or HFlags, Been_here    ; Flag for later
  213.  
  214.     call Back_to_normal_ds
  215.  
  216.     ASSUME ds:DataS, es:DataS
  217.  
  218.     mov al, m7171        ; Pick up current 7171 mode
  219.     mov Old_7171_mode, al    ; Store it for later test
  220.  
  221.     call Use_our_own_ds
  222.  
  223.     ASSUME ds:HAlloc, es:HAlloc
  224.  
  225.     jmp SHORT HLP_1a
  226.  
  227.     ASSUME ds:DataS, es:DataS
  228.  
  229. HLP_1:    call Use_our_own_ds    ; Switch to HAlloc segment
  230.  
  231.     ASSUME ds:HAlloc, es:HAlloc
  232.  
  233. HLP_1a:    call Build_box        ; Build outline / background for Help window
  234.  
  235.     mov ax, First_line    ; Address of start at Help text
  236.     mov Current_line, ax    ; Set up as current position
  237.  
  238. HLP_2:    call Fill_frame        ; Get frame ready
  239.     call Do_the_screen    ; Display this frame
  240.  
  241.     call Check_keystrokes    ; See what to do next
  242.     test HFlags, Bye_bye    ; Time to leave?
  243.      jz HLP_2        ;  No, go update the frame
  244.  
  245.     jmp Back_to_normal_ds    ; Done here
  246.  
  247.  
  248.     PUBLIC Bombed
  249.  
  250.     ASSUME ds:DataS, es:DataS
  251. Bombed:    call Boop        ; Bombed, make a noise
  252.     or HFlags, Bye_bye    ; Go home
  253.     ret
  254.     ASSUME ds:HAlloc, es:HAlloc
  255.  
  256.  
  257.     PUBLIC Build_Help_database
  258.  
  259. Build_Help_database:
  260.  
  261.     call Back_to_normal_ds    ; Need old ds to open file
  262.  
  263.     ASSUME ds:DataS, es:DataS
  264.  
  265.     mov ax, OFFSET Help_file_name ; Name of file to get
  266.     cmp m7171, 0        ; In 7171 mode?
  267.      je BUI_0
  268.  
  269.     mov ax, OFFSET Help_file_7171 ; Name of the other file
  270.  
  271. BUI_0:    call spath        ; Search path for file, DSK: first
  272.      jnc BUI_ok        ;  Got it, go work with it
  273.  
  274.     mov dx, OFFSET Cant_find_file ; Complain
  275.     cmp m7171, 0        ; In 7171 mode?
  276.      je BUI_1
  277.  
  278.     mov dx, OFFSET Cant_find_7171 ; Complain about missing 7171 file
  279.  
  280. BUI_1:    call Do_mode_line_error ; Wait for a key
  281.     jmp Use_our_own_ds    ; Reset ds and return NG
  282.  
  283. BUI_ok:
  284.     mov dx, ax        ; Copy ptr to name to dx
  285.     mov ax, (Open2*100h) + 0 ; Open file for input
  286.     int DOS            ; Try to open the file
  287.      jc Bombed        ;  Huh?
  288.  
  289.     mov bx, ax        ; Copy handle to bx
  290.  
  291.     call Use_our_own_ds    ; Back to our own version
  292.  
  293.     ASSUME ds:HAlloc, es:HAlloc
  294.  
  295.     mov di, OFFSET Help_database ; Ptr to start of our database
  296.     mov First_line, di    ; Save ptr to start for later
  297.     mov Current_line, di    ; Also a ptr for making Last_line later
  298.     cld            ; Build forwards
  299.  
  300. BUI_disk_read:
  301.     mov ah, ReadF2        ; Code to read from file, handle still in bx
  302.     mov cx, SIZE Help_file_buffer ; Number of characters to try for
  303.     mov dx, OFFSET Help_file_buffer ; Where to put them
  304.     int DOS            ; Read from the help file
  305.      jc BUI_finish        ;  Stop on error
  306.  
  307.     or ax, ax        ; Check for zero bytes read
  308.      jz BUI_finish        ; Hit EOF, go finish it up
  309.  
  310.     mov cx, ax        ; Byte count for this record
  311.     inc cx            ; We decr once too many times
  312.     mov si, OFFSET Help_file_buffer ; Ptr to buffer
  313.  
  314. BUI_lp:    loop BUI_next_char    ; If more chars, go get one
  315.     jmp SHORT BUI_disk_read    ; Buffer is empty, try to refill it
  316.  
  317. BUI_next_char:
  318.     lodsb            ; Get the next byte
  319.  
  320.     cmp al, CtlZ        ; Control-Z?
  321.      jl BUI_control        ;  Less, check for control char
  322.      je BUI_lp        ;  Ignore control Z
  323.  
  324.     stosb            ; Store the char
  325.     jmp BUI_lp        ; Go do another one
  326.  
  327. BUI_control:
  328.     cmp al, Lf        ; Line feed?
  329.      jne BUI_lp        ;  No
  330.  
  331.     sub al, al        ; Make a zero
  332.     stosb            ; Tie off the last line
  333.  
  334.     mov ax, Current_line    ; Pick up trailing ptr
  335.     mov Last_line, ax    ; Assume it's the last line, for now
  336.     mov Current_line, di    ; Update trailing ptr for next round
  337.  
  338.     jmp BUI_lp        ; Go get another character
  339.  
  340. BUI_finish:
  341.     sub al, al        ; Make a zero
  342.     mov cx, 25        ; Make several blank lines after help database
  343.     rep stosb        ; Write a string of zeros
  344.  
  345.     mov ah, 3eh        ; Code to close a file
  346.     int DOS            ; Close the file
  347.  
  348.     mov di, Last_line
  349.     mov Current_line, di
  350.     mov cx, Len - 3        ; Maximum number of lines to move
  351.     call PgUp_lp        ; Get a new DI pointing to proper line
  352.     mov Last_top_line, di    ; Save for later
  353.  
  354.     ret            ; Done here
  355.  
  356.     PUBLIC Build_box
  357.  
  358. Build_box:
  359.  
  360.     cld            ; Forwards
  361.     mov di, OFFSET Our_Image ; Our own buffer
  362.     mov cx, Number_of_chars_on_PC_screen ; How many chars
  363.     lds si, Screen_Image_ptr ; Addr of copy of screen at entry
  364.     rep movsw        ; Install incoming screen as background
  365.     push es            ; Our segment
  366.     pop ds            ; Set up ds again
  367.  
  368. Wid=Number_of_columns-(2*Help_window_left) ; How many columns
  369. Len=Number_of_rows_PC-(2*Help_window_top) ; How many rows
  370.  
  371. Color_attr=1eh            ; Bright yellow on blue
  372. Mono_attr=70h            ; Black on white
  373.  
  374.  
  375.  %OUT >> About half way through source file
  376.  
  377.  
  378. Upper_left=218            ; Box drawing chars
  379. Upper_right=191
  380. Lower_left=192
  381. Lower_right=217
  382. Horizontal=196
  383. Vertical=179
  384.  
  385.     mov ax, Help_window_top    ; Row number of top of window
  386.     mov Which_row, ax    ; Save it for later
  387.     call Make_new_ptr    ; Get a new DI
  388.  
  389.  
  390. ; Set up proper attribute based on card type
  391.  
  392.     mov bh, Mono_attr    ; Assume mono
  393.     call Back_to_normal_ds
  394.     ASSUME ds:DataS, es:DATAS
  395.  
  396.     cmp Force_mono, 0    ; Are we stuck with mono?
  397.      jne MON_0        ;  Yes
  398.  
  399.     call Get_Screen_Segment
  400.     cmp ax, 0b000h        ; Mono?
  401.      je MON_0        ;  It is, go use it
  402.  
  403.     mov bh, Color_attr    ; Color, use it instead
  404.  
  405.     PUBLIC MON_0
  406.  
  407. MON_0:    mov ah, bh        ; Install in ah
  408.     call Use_our_own_ds
  409.     ASSUME ds:HAlloc, es:HAlloc
  410.  
  411. ; Do top row of help window
  412.  
  413.     mov al, Upper_left
  414.     stosw
  415.  
  416.     mov al, Horizontal
  417.     mov cx, Wid - 2
  418.     rep stosw
  419.  
  420.     mov al, Upper_right
  421.     stosw
  422.  
  423.     inc Which_row        ; Bump to next row
  424.     call Make_new_ptr    ; Point to it
  425.  
  426. ; Do the middle rows of the help window
  427.  
  428.     mov cx, Len - 2        ; Number of rows to do
  429.  
  430.     PUBLIC LP_1
  431.  
  432. LP_1:    push cx
  433.  
  434.     mov al, Vertical
  435.     stosw
  436.  
  437.     mov al, Space
  438.     mov cx, Wid - 2
  439.     rep stosw
  440.  
  441.     mov al, Vertical
  442.     stosw
  443.  
  444.     pop cx
  445.  
  446.     inc Which_row        ; Bump to next row
  447.     call Make_new_ptr    ; Point to it
  448.  
  449.     loop LP_1
  450.  
  451. ; Do bottom row of help window
  452.  
  453.     mov al, Lower_left
  454.     stosw
  455.  
  456.     mov al, Horizontal
  457.     mov cx, Wid - 2
  458.     rep stosw
  459.  
  460.     mov al, Lower_right
  461.     stosw
  462.  
  463.     mov ax, (100h * Help_window_top) + Help_window_left ; New position
  464.     mov Our_cursor, ax    ; Set it for Put_Screen
  465.  
  466.     ret
  467.  
  468.  
  469. ; Set up a pointer to this row
  470.  
  471.     PUBLIC Make_new_ptr
  472.  
  473. Make_new_ptr:
  474.     push ax            ; Save reg
  475.     mov ax, Which_row    ; Row number of topmost row
  476.     mov bh, 2 * Number_of_columns ; Convert to bytes 
  477.     mul bh
  478.     add ax, (2 * Help_window_left) + OFFSET Our_Image ; Point to our
  479.                 ;  image, proper column
  480.     mov di, ax        ; Set up as destination
  481.     pop ax            ; Restore reg
  482.     ret            ; Go use it
  483.  
  484.  
  485.     PUBLIC Fill_frame
  486.  
  487. Fill_frame:
  488.     cld            ; Build forwards
  489.     mov ax, Help_window_top + 1 ; Row number to start writing to
  490.     mov Which_row, ax    ; Save it
  491.     call Make_new_ptr    ; Get a new DI
  492.     add di, 4        ; Skip over border, and another space
  493.  
  494.     mov si, Current_line    ; Start at current position in help text
  495.     mov cx, Len - 2        ; Number of rows to write
  496.  
  497. FIL_lp_outer:
  498.     push cx            ; Save outer loop counter
  499.     mov cx, Wid - 4        ; Number of chars we can fit in a line
  500.  
  501. FIL_lp_inner:
  502.     lodsb            ; Pick up the next byte
  503.     or al, al        ; Check for zero
  504.      jnz FIL_inner_bot    ;  Char is ok, use it
  505.  
  506.     dec si            ; Back up to re-read the zero byte
  507.     mov al, Space        ; Pad character
  508.  
  509. FIL_inner_bot:
  510.     stosb            ; Store this char
  511.     inc di            ; Skip attribute
  512.     loop FIL_lp_inner    ; Go do another char
  513.  
  514. ; End of inner loop, skip chars until we hit a zero byte
  515.  
  516. FIL_end_of_inner:
  517.     lodsb            ; Pick up the next byte
  518.     or al, al        ; Is it zero?
  519.      jnz FIL_end_of_inner    ;  Skip chars until we hit a zero
  520.  
  521.     inc Which_row        ; Move to next row
  522.     call Make_new_ptr    ; Get a new DI
  523.     add di, 4        ; Skip over border and first column
  524.  
  525.     pop cx            ; Restore outer loop counter
  526.     loop FIL_lp_outer    ; Go try for another line
  527.  
  528.     ret
  529.  
  530.  
  531.     PUBLIC Check_keystrokes
  532.  
  533. Check_keystrokes:
  534.  
  535.     call Back_to_normal_ds
  536.     call Do_mode_line    ; Update the mode line
  537.     call Use_our_own_ds
  538.  
  539.     mov di, OFFSET Our_image + (24 * 160) ; Where our copy is
  540.     mov cx, Number_of_columns ; Size of mode line
  541.     lds si, Mode_line_ptr    ; Point to real mode line
  542.     ASSUME ds:Nothing
  543.     cld            ; Forwards
  544.     rep movsw        ; Copy the mode line to our buffer
  545.     push es            ; Restore ds
  546.     pop ds
  547.     ASSUME ds:HAlloc
  548.  
  549.     call Do_the_screen    ; Install image
  550.  
  551.     mov ah, 1        ; Code to see if a char is ready
  552.     int Kb            ; Have BIOS tell us
  553.      jz Check_keystrokes    ;  None, waste time on mode line
  554.  
  555.     sub ah, ah        ; Zero is code to read the char
  556.     int Kb            ; Have BIOS get it for us
  557.  
  558.     call Back_to_normal_ds    ; Check_Table requires normal ds
  559.     mov al, ah        ; Copy scan code to al
  560.     mov bx, OFFSET Actions    ; Action table
  561.     mov cx, N_Characters    ; Number of scan codes to check
  562.     mov dx, OFFSET Characters ; The character table
  563.     jmp Check_Table        ; Go dispatch to the right routine
  564.  
  565.     PUBLIC Do_the_screen, Do_boop
  566.  
  567. Do_the_screen:
  568.     mov bx, OFFSET Our_Image ; Set ptr to our screen
  569.  
  570.     mov ax, Normal_ds    ; Put_Screen likes normal ds
  571.     mov ds, ax
  572.     ASSUME ds:DataS
  573.     or Screen_flags, Screen_changed ; Flag that Put_Screen has to work
  574.     call Put_Screen        ; Update screen
  575.  
  576.     push es            ; Reset ds
  577.     pop ds    
  578.     ASSUME ds:HAlloc
  579.     ret            ; Done here
  580.  
  581. Do_boop:
  582.     call Back_to_normal_ds    ; Boop requires this
  583.     call Boop        ; Give low beep
  584.     call Use_our_own_ds    ; Ours again
  585.     jmp Check_keystrokes    ; Try again
  586.  
  587. Do_Home:
  588.     call Use_our_own_ds    ; Ours again
  589.     mov di, First_line    ; Button to go to first line
  590.     cmp di, Current_line    ; Are we on it already?
  591.      je Do_boop        ;  Yeah, complain for consistency
  592.  
  593.     mov Current_line, di    ; Otherwise, go to first line
  594.     ret
  595.  
  596. Do_End:    call Use_our_own_ds    ; Ours again
  597.     mov di, Last_top_line    ; Button to go to last frame line
  598.     cmp di, Current_line    ; Are we on it already?
  599.      je Do_boop        ;  Yeah, complain for consistency
  600.  
  601.     mov Current_line, di    ; Otherwise, go to it
  602.     ret
  603.  
  604. Do_PgUp:
  605.     call Use_our_own_ds    ; Ours again
  606.     mov di, Current_line    ; Line we are on
  607.     cmp di, First_line    ; First line we can be on
  608.      je Do_boop        ;  Can't go up
  609.  
  610.     mov cx, Len - 3        ; Maximum number of lines to move
  611.     jmp SHORT PgUp_lp
  612.  
  613. Do_PgDn:
  614.     call Use_our_own_ds    ; Ours again
  615.     mov di, Current_line    ; Line we are on
  616.     cmp di, Last_line    ; Last line we can be on
  617.      je Do_boop        ;  Can't go down
  618.  
  619.     mov cx, Len - 3        ; Maximum number of lines to move
  620.     jmp SHORT PgDn_lp
  621.  
  622. Do_Up:    call Use_our_own_ds    ; Ours again
  623.     mov di, Current_line    ; Line we are on
  624.     cmp di, First_line    ; First line we can be on
  625.      je Do_boop        ;  Can't go up
  626.     jmp SHORT Up
  627.  
  628. Do_Down:
  629.     call Use_our_own_ds    ; Ours again
  630.     mov di, Current_line    ; Line we are on
  631.     cmp di, Last_line    ; Last line we can be on
  632.      je Do_boop        ;  Can't go down
  633.     jmp SHORT Down
  634.  
  635. CHK_bye:
  636.     call Use_our_own_ds    ; Ours again
  637.     or HFlags, Bye_bye    ; Flag the exit
  638.     ret            ; Done here
  639.  
  640. PgUp_lp:
  641.     push cx            ; Other routine clobbers this
  642.     call Up            ; Try to move up
  643.     mov di, Current_line    ; Line we are on
  644.     cmp di, First_line    ; First line we can be on
  645.      je CHK_pop        ;  Can't go up, pop reg and return
  646.     pop cx            ; Restore reg
  647.     loop PgUp_lp        ; Do the rest
  648.     ret            ; Done here
  649.  
  650. PgDn_lp:
  651.     push cx            ; Other routine clobbers this
  652.     call Down        ; Try to move down
  653.     mov di, Current_line    ; Line we are on
  654.     cmp di, Last_line    ; Last line we can be on
  655.      je CHK_pop        ;  Can't go up, pop reg and return
  656.     pop cx            ; Restore reg
  657.     loop PgDn_lp        ; Do the rest
  658.     ret            ; Done here
  659.  
  660. Down:    mov cx, 80        ; Max number of chars to scan
  661.     sub al, al        ; Make a zero
  662.     cld            ; Forwards
  663.     repne scasb        ; Go looking for a zero byte
  664.  
  665.     mov Current_line, di    ; Now pointing to beginning of next line
  666.     ret
  667.  
  668. Up:    sub di, 2        ; Skip back over terminator
  669.     mov cx, 80        ; Max number of chars to scan
  670.     sub al, al        ; Make a zero
  671.     std            ; Backwards
  672.     repne scasb        ; Go looking for a zero byte
  673.  
  674.     add di, 2        ; Skip forwards over terminator
  675.     mov Current_line, di    ; Now pointing to beginning of previous line
  676.     ret
  677.  
  678. CHK_pop:
  679.     pop cx            ; Restore reg
  680.     ret
  681.  
  682. Back_to_normal_ds:
  683.     push ax            ; Save reg
  684.     mov ax, Normal_ds    ; Pick up addr of DataS segment
  685.     mov ds, ax        ; Copy to ds
  686.     mov es, ax        ;  and es
  687.     pop ax            ; Restore reg
  688.     ret            ;  and return
  689.  
  690.     ASSUME ds:DataS, es:DataS
  691.  
  692. Use_our_own_ds:
  693.     push ax            ; Save reg
  694.     mov ax, HAlloc_ptr    ; Pick up addr of HAlloc segment
  695.     mov ds, ax        ; Copy to ds
  696.     mov es, ax        ;  and es
  697.     pop ax            ; Restore reg
  698.     ret            ;  and return
  699.  
  700. Helper    ENDP
  701.  
  702. Do_mode_line_error PROC
  703.  
  704.     call Save_mode_line    ; Ask for a save
  705.     call PutErr_PC        ; Play with mode line
  706.     call Bombed        ; Make noise
  707.     sub ah, ah        ; Code to read a character
  708.     int Kb            ; Wait until user hits key
  709.     jmp Restore_mode_line    ; Ask for a restore, ret from there
  710.  
  711. Do_mode_line_error ENDP
  712.  
  713.  
  714. ; Save the mode line for later restoral
  715.  
  716. Save_mode_line PROC
  717.  
  718.     push ds            ; Save ds
  719.     call Get_address    ; Get new ds into ax
  720.     mov ds, ax        ; Store the new seg addr
  721.     mov si, (Number_of_rows_PC-1)*2*Number_of_columns ; Offset of line 25
  722.     mov di, OFFSET Saved_mode_line ; Where to copy it
  723.     mov cx, Number_of_columns
  724.     cld            ; Forwards
  725.     rep movsw        ; Save the line
  726.     pop ds            ; Restore ds
  727.     ret
  728.  
  729. Save_mode_line ENDP
  730.  
  731.  
  732. ; Restore the mode line
  733.  
  734. Restore_mode_line PROC
  735.  
  736.     push es            ; Save es
  737.     call Get_address    ; Get new es into ax
  738.     mov es, ax        ; Store the new seg addr
  739.     mov si, OFFSET Saved_mode_line ; Where copy is
  740.     mov di, (Number_of_rows_PC-1)*2*Number_of_columns ; Offset of line 25
  741.     mov cx, Number_of_columns
  742.     cld            ; Forwards
  743.     rep movsw        ; Restore the line
  744.     pop es            ; Restore es
  745.     ret
  746.  
  747. Restore_mode_line ENDP
  748.  
  749.  
  750. ; Get address of segment of currently-displayed video page
  751.  
  752. Get_address PROC
  753.  
  754.     mov ax, 0B000h        ; Mono, maybe
  755.     cmp Which_card, 0     ; Is it?
  756.      je Go_back        ;  Yes
  757.  
  758.     sub bh, bh        ; Zero high half of bx
  759.     mov bl, Which_page    ; The page we are on in the color card
  760.     shl bx, 1        ; Double for word offset into table
  761.     mov ax, Video_page_addresses[bx] ; Pick up the address for the page
  762.  
  763. Go_back:
  764.     ret
  765.  
  766. Get_address ENDP
  767.  
  768. Code    ENDS
  769.  
  770.     END
  771. 
  772.